package cczhr.com.aoptest;

import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AspectTest {
    //Around和After是不能同时作用在同一个方法上
    //execution是在被切入的方法中，call是在调用被切入的方法前或者后
    private static final String TAG = "cczhr-----";


    //@Before具体的插入点 第一个*为返回值 （）表示方法参数
    @Before("execution(* cczhr.com.aoptest.MainActivity.on*(android.os.Bundle))")
    public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
        String key = joinPoint.getSignature().toString();
        Log.d(TAG, "^^^^^^^^^^^^^^^^^^^^onActivityMethodBefore: " + key);
    }

    @After("execution(* cczhr.com.aoptest.MainActivity.on*(android.os.Bundle))")
    public void onActivityMethodAfter(JoinPoint joinPoint) throws Throwable {
        String key = joinPoint.getSignature().toString();
        Log.e(TAG, "********************onActivityMethodAfter: " + key);
    }

    /*  @Around("execution(* cczhr.com.aoptest.MainActivity.testAOP())")
      public void onActivityMethodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
          String key = proceedingJoinPoint.getSignature().toString();
          Log.d(TAG, "--------------------onActivityMethodAroundFirst: " + key);
          proceedingJoinPoint.proceed();
          Log.d(TAG, "--------------------onActivityMethodAroundSecond: " + key);
      }*/
    @Pointcut("execution(@cczhr.com.aoptest.DebugTool * *(..))&& @annotation(debugTool)")  //@annotation(debugTool)用来表示debugTool参数是注解类型
    public void DebugToolMethod(DebugTool debugTool) {
    }


   // @Around 会替换原先执行的代码，但如果你仍然希望执行原先的代码，可以使用joinPoint.proceed()。
   @Around("DebugToolMethod(debugTool)")
    public void onDebugToolMethodBefore(ProceedingJoinPoint joinPoint,DebugTool debugTool) throws Throwable {
     //  Log.e(TAG, "before->" + joinPoint.getTarget().toString() + "#" + joinPoint.getSignature().getName());


        String key = joinPoint.getSignature().toString();
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            Log.d(TAG, "第" + (i + 1) + "个参数为:" + args[i]);//方法传入的参数

        }

        Log.d(TAG, "$$$$$$$$$$$$$$$$$$注解: " + debugTool.resourceId());
        Log.d(TAG, "$$$$$$$$$$$$$$$$$$onDebugToolMethodBefore: " + key);
        joinPoint.proceed();
    }



    @Pointcut("get(int cczhr.com.aoptest.MainActivity.data)")
    public void fieldget() {}
    @Around("fieldget()")
    public int fieldget(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        Object proceed = thisJoinPoint.proceed();
        Log.d(TAG,thisJoinPoint.toLongString());
        Log.d(TAG, thisJoinPoint.getSignature().getName());
        Log.d(TAG,"--->"+proceed);
        return (int) proceed; //必须return 否则报错（applying to join point that doesn't return void: field-get）
    }


    @After("execution(cczhr.com.aoptest.Demo.new(..))")//构造方法
    public void beforeConstructorExecution(JoinPoint joinPoint) {
        Demo d=(Demo) joinPoint.getTarget();//this 返回代理对象 返回目标对象
       // d.setAge(6);
        Log.e(TAG, "连接点所在位置的相关信息"+ joinPoint.toString()+d.getAge() );
        Log.e(TAG, "连接点所在位置的简短信息" +joinPoint.toShortString());
        Log.e(TAG, "连接点所在位置的全部信息" +joinPoint.toLongString());
        Log.e(TAG, "连接点类型" +joinPoint.getKind());
        Log.e(TAG, "AOP代理对象" +joinPoint.getThis().getClass().getName()+"哈希码"+joinPoint.getThis().hashCode());
        Log.e(TAG, "目标对象" +joinPoint.getTarget().getClass().getName()+"哈希码"+joinPoint.getTarget().hashCode());
        Log.e(TAG, "方法参数数组" +joinPoint.getArgs().length);
        Log.e(TAG, "连接点所在文件中的位置" +joinPoint.getSourceLocation());
        Log.e(TAG, "连接点对象信息" +joinPoint.getSignature().toString()+"----"+joinPoint.getSignature().toLongString()+"----"+joinPoint.getSignature().getModifiers());
    }


    @Around("get(int cczhr.com.aoptest.Demo.age)")//读变量 替换访问age的代码
    public int aroundFieldGet(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行原代码
        Object obj = joinPoint.proceed();
        int age = Integer.parseInt(obj.toString());
        Log.e(TAG, "age: " + age);
        return 100;
    }
    //withincode
    @Around("set(int cczhr.com.aoptest.Demo.age)&& !withincode(cczhr.com.aoptest.Demo.new(..))")//写变量 替换设置age的代码 这里去除构造函数的替换
    public void aroundFieldSet(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e(TAG, "around->" + joinPoint.getTarget().toString() + "#" + joinPoint.getSignature().getName());
    }

    @Before("staticinitialization(cczhr.com.aoptest.Demo)")  //静态代码块
    public void beforeStaticBlock(JoinPoint joinPoint) {
        Log.d(TAG, "beforeStaticBlock: ");
    }



    @AfterThrowing(pointcut = "call(* cczhr.com.aoptest.MainActivity.getMessage(..))", throwing = "throwable")//捕获抛出的异常
    public void anyFuncThrows(Throwable throwable) {
        Log.e(TAG, "hurtThrows: ", throwable);
    }

    @Before("handler(java.lang.Exception)")//捕获加了try catch的异常 只能精准匹配  handler 不支持 @After 与 @Around，且异常只支持编译时匹配
    public void handler() {
        Log.e(TAG, "handler");
    }


    @AfterReturning(pointcut = "execution(* cczhr.com.aoptest.MainActivity.returnNumber(..))", returning = "myNumber")//获取返回值
    public void getMyNumber(JoinPoint joinPoint,int myNumber) {
        Log.d(TAG, "getmyNumber: " +myNumber+"---"+joinPoint.toString());
    }


//


}